package java_thinking.unit_21._21_6;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

import static java_thinking.unit_21._21_5.LaunderThrowable.launderThrowable;

/**
 * @Desc:   6-13 使用 Future 等待图像下载
 *          场景：为了使页面渲染器实现更高的并发性，首先将渲染过程氛围两个任务，一个是渲染
 *          所有文本，另一个是下载所有图像(其中一个任务时CPU密集型，而另一个任务时I/O密集型
 *          因此这种方法即使在但CPU上也能提升性能)
 * @author: cww
 * @DateTime: 2019-06-11 22:09
 */

public abstract class FutureRenderer {
    private final ExecutorService exec = Executors.newCachedThreadPool();
    void renderPage(CharSequence source) {
        final List<ImageInfo> imageInfos = scanForImageInfo(source);
        //创建  Callable 来下载所有图像，并提交到 ExecutorService 线程池中，当主任务需要图像时会
        //等待 Future.get 返回结果
        Callable<List<ImageData>> task = new Callable<List<ImageData>>() {
            @Override
            public List<ImageData> call() throws Exception {
                List<ImageData> result = new ArrayList<>();
                for (ImageInfo imageInfo : imageInfos) {
                    result.add(imageInfo.downloadImage());
                }
                return result;
            }
        };
        Future<List<ImageData>> future = exec.submit(task);
        //渲染文字
        renderText(source);
        try {
            //如果下载图片线程未完成，将等待
            List<ImageData> imageData = future.get();
            for (ImageData data : imageData) {
                //遍历渲染图片
                renderImage(data);
            }
        } catch (InterruptedException e) {
            //重新设置线程的中断状态
            Thread.currentThread().interrupt();
            //由于不需要结果，因此取消任务
            future.cancel(true);
        } catch (ExecutionException e) {
            throw launderThrowable(e.getCause());
        }

    }
    interface ImageInfo {
        ImageData downloadImage();
    }

    interface ImageData {
    }
    abstract List<ImageInfo> scanForImageInfo(CharSequence s);
    abstract void renderImage(ImageData i);
    abstract void renderText(CharSequence s);
}
